package com.cyao;

import com.alibaba.fastjson.JSON;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 获取豆瓣电影评分
 *
 * @author ChangYao
 */
@RestController
@SpringBootApplication(exclude = {RedisRepositoriesAutoConfiguration.class})
public class Application {
    private final Logger logger = LoggerFactory.getLogger("DouBanApplication");

    public static void main(String[] args) {
        System.out.println("以jar包方式启动...当前JAVA版本..." + System.getProperty("java.version"));

        SpringApplication.run(Application.class, args);
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("/")
    public String home() {
        return "Hello World !";
    }

    @GetMapping("/search")
    public List<MovieInfo> get(@RequestParam String q, @RequestParam(defaultValue = "1") Integer limit) {
        logger.info("query key {}", q);
        List<MovieInfo> movieInfos = getAndCacheRedis(q);
        return CollectionUtils.isEmpty(movieInfos) ? new ArrayList<>() : movieInfos.stream().limit(limit).collect(Collectors.toList());
    }

    /**
     * 获取评分并缓存到Redis
     *
     * @param q
     * @return
     */
    private List<MovieInfo> getAndCacheRedis(String q) {
        String key = "cache_" + q;
        String cache = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(cache)) {
            List<MovieInfo> movieInfos = query(q);
            if (movieInfos != null) {
                stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(movieInfos), 24, TimeUnit.HOURS);
                return movieInfos;
            } else {
                return new ArrayList<>();
            }
        } else {
            return JSON.parseArray(cache, MovieInfo.class);
        }
    }

    /**
     * 获取豆瓣评分
     *
     * @param query 搜索关键词
     * @return
     */
    private List<MovieInfo> query(String query) {
        try {
            Pattern pattern = Pattern.compile("\\d+(.\\d+)?$");
            Document root = Jsoup.connect("https://m.douban.com/search/?query=" + query + "&type=1002").userAgent(MovieInfo.USER_AGENT).get();
            Elements results = root.getElementsByClass("search_results_subjects");
            if (!results.isEmpty()) {
                Elements elements = results.get(0).getElementsByTag("li");
                return elements.stream().map(li -> {
                    String title = li.getElementsByClass("subject-title").get(0).text();
                    String rating = li.getElementsByTag("span").last().text();
                    String href = li.getElementsByTag("a").get(0).attr("abs:href");
                    String img = li.getElementsByTag("img").get(0).attr("src");
                    logger.info("query key {} title {} rating {}", query, title, rating);
                    return new MovieInfo(title, rating, href, img);
                }).filter(o -> pattern.matcher(o.getRating()).matches()).limit(3).collect(Collectors.toList());
            }
        } catch (Exception e) {
            logger.info("query key {} error {}", query, e.getMessage());
        }
        return null;
    }

    public static class MovieInfo {
        static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
        private String title;//电影名称
        private String rating;//评分
        private String href;//豆瓣链接
        private String img;//图片地址

        public MovieInfo() {

        }

        MovieInfo(String title, String rating, String href, String img) {
            this.title = title;
            this.rating = rating;
            this.href = href;
            this.img = img;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getRating() {
            return rating;
        }

        public void setRating(String rating) {
            this.rating = rating;
        }

        public String getHref() {
            return href;
        }

        public void setHref(String href) {
            this.href = href;
        }

        public String getImg() {
            return img;
        }

        public void setImg(String img) {
            this.img = img;
        }
    }
}
